package com.htl.exampro.base.filter;

import com.htl.exampro.base.utils.JwtUtil;
import com.htl.exampro.base.utils.UserUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        String uri = request.getRequestURI();
        // 放行登录/注册请求
        if (uri.equals("/user/user/login")
                || uri.equals("/user/user/register")
                || uri.equals("/user/user/sendCode")
                || uri.contains("/swagger-ui")
                || uri.contains("/v3/api-docs")
                || uri.contains("/actuator")
                || uri.contains("/error")) {
            chain.doFilter(request, response);
            return;
        }
        try {
            // Token验证逻辑
            String token = request.getHeader("Authorization");
            if (!StringUtils.hasText(token)) {
                sendError(response, 401, "未登录，请登录后再试！");
                return;
            }
            Claims claims = jwtUtil.getClaimsFromToken(token);
            String tokenKey = UserUtil.getTokenKey((Long) claims.get(UserUtil.USER_ID));
            if (!redisTemplate.hasKey(tokenKey)) {
                sendError(response, 401, "未登录，请登录后再试！");
                return;
            }
            // 刷新Redis过期时间
//            redisTemplate.expire(UserUtil.getTokenKey(), jwtUtil.getExpiration(), TimeUnit.MINUTES);
            // 构建完整Authentication对象
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
//            List<SimpleGrantedAuthority> authorities = ((List<?>) claims.get("auth"))
//                    .stream()
//                    .map(a -> new SimpleGrantedAuthority(a.toString()))
//                    .collect(Collectors.toList());
            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(claims, null, authorities);
            SecurityContextHolder.getContext().setAuthentication(auth);

            chain.doFilter(request, response);
        } catch (JwtException e) {
            sendError(response, 401, "登录已失效，请重新登录！");
        }
    }

    private void sendError(HttpServletResponse res, int code, String msg) throws IOException {
        res.setContentType("application/json;charset=UTF-8");
        res.setStatus(HttpStatus.OK.value());
        res.getWriter().write(String.format("{\"code\":%d,\"message\":\"%s\"}", code, msg));
    }

}